package org.nuplay;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.*;

import com.illposed.osc.OSCMessage;

public class NuPlayArduinoClient extends JFrame implements ActionListener, WindowListener {
	
	private DatagramSocket client_socket;
	private DatagramPacket packet;
	private JComboBox com_devices_choose;
	private JTextField ip_number_choose;
	private JButton connect_button;
	private boolean connected;
	private JLabel error_label;
	//
	private SerialPort serialPort;
	private NuPlayArduinoSend sender;
	private InputStream in;
	
	//
	private JComboBox channel;
	
	public NuPlayArduinoClient() {
		connected = false;
		try {
			UIManager.setLookAndFeel(
			        UIManager.getCrossPlatformLookAndFeelClassName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		build_ui();
		init_com_devices();
	}

	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == connect_button) {
			if (connected) {
				disconnect("ready...");	
			} else {
				connect();
			}
		}
	}
	
	private void build_ui() {
		addWindowListener(this);
		getContentPane().setLayout( new BorderLayout() );

		
		
		
		JPanel topPanel = new JPanel();
		topPanel.setLayout( null );
		getContentPane().add( topPanel, BorderLayout.CENTER );
		
		JLabel label_midi_device = new JLabel("Which COM-port to use?");
		label_midi_device.setBounds(20, 20, 200, 20);
		com_devices_choose = new JComboBox();
		com_devices_choose.setBounds( 20, 40, 260, 20 );
		topPanel.add(label_midi_device);
		topPanel.add(com_devices_choose);
	
		JLabel label_ip_address = new JLabel("Where is NuPlay running at?");
		label_ip_address.setBounds(20,70, 200, 20);
		
		ip_number_choose = new JTextField();
		ip_number_choose.setBounds( 20, 90, 260, 20 );
		try {
			ip_number_choose.setText(InetAddress.getLocalHost().getHostAddress());
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		
		topPanel.add(label_ip_address);
		topPanel.add(ip_number_choose);
		
		
		JLabel channel_text = new JLabel("Which channel to use?");
		channel_text.setBounds(20,120, 200, 20);
	
		
		channel = new JComboBox();
		for(int i=0; i < 32;i++) {
			channel.addItem(new Integer(i + 1));
		}
		channel.setBounds( 20, 140, 260, 20 );
		topPanel.add(channel_text);
		topPanel.add(channel);
		
		connect_button = new JButton("Connect to NuPlay.");
		connect_button.addActionListener(this);
		connect_button.setBounds( 20, 180, 200, 20 );
		topPanel.add(connect_button);
		
		error_label = new JLabel("ready...");
		error_label.setForeground(new Color(255,0,0));
		error_label.setBounds(20, 210,200,20);
		topPanel.add(error_label);
		

		java.net.URL imageURL = NuPlayArduinoClient.class.getResource("nuplay.png");
		if (imageURL != null) {
			ImageIcon icon = new ImageIcon(imageURL);
			JLabel image_label = new JLabel(icon);
			this.setIconImage(icon.getImage());
			image_label.setBounds( 260, 160, 50, 77 );
			topPanel.add(image_label);
		}
	}
	
	
	private void init_com_devices() {
//			midi_devices_choose.addItem(midi_devices[i].getName());
		   java.util.Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
	        while ( portEnum.hasMoreElements() ) 
	        {
	            CommPortIdentifier portIdentifier = (CommPortIdentifier) portEnum.nextElement();
	            if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) {
	            	com_devices_choose.addItem(portIdentifier.getName());
	            } 
	           }      
	}
	
	private void close_midi_device() {
		if (sender != null) {
			sender.close();
			sender = null;
		}
		if (serialPort != null) {
			System.out.println("closing!");
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				in = null;
			}
			serialPort.close();
			serialPort = null;
		}
	}
	
	private void open_midi_device() {
			//midi_devices_choose.getSelectedItem()
		try {
		  CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier("" + com_devices_choose.getSelectedItem());
	        if ( portIdentifier.isCurrentlyOwned() )
	        {
	        	
	        	error_label.setText("Error: Port is currently in use");
	        }
	        else
	        {
	            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
	            
	            if ( commPort instanceof SerialPort )
	            {
	                serialPort = (SerialPort) commPort;
	                serialPort.setSerialPortParams(115200,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
	                
	              in = serialPort.getInputStream();
	                sender = new NuPlayArduinoSend(this, in, (Integer)channel.getSelectedItem(), InetAddress.getByName(ip_number_choose.getText()), error_label);
		
	            }
	            else
	            {
	            	error_label.setText("Error: Only serial ports are handled by this example.");
	            }
	        }     
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public void disconnect(String in_message) {
		connected = false;
		connect_button.setText("Connect to NuPlay.");
		error_label.setText(in_message);
		close_midi_device();
	}
	
	private void connect() {
		connected = true;
		connect_button.setText("Disconnect from NuPlay.");
		error_label.setText("wait for input...");
		open_midi_device();
	}
	
	public void close() {
		System.exit(0);
	}

	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		JFrame main_window = new NuPlayArduinoClient();
		main_window.setSize(320, 270);
		main_window.setTitle("NuPlay ARDUINO client V1.0");
		main_window.setVisible(true);
	}

	public void windowActivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowClosed(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowClosing(WindowEvent e) {
		close();
		
	}

	public void windowDeactivated(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowDeiconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowIconified(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}

	public void windowOpened(WindowEvent e) {
		// TODO Auto-generated method stub
		
	}
	
}
